/*
 *  ssp.h
 *
 *  Copyright (C) 2003 Russell King, All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This driver supports the following PXA CPU/SSP ports:-
 *
 *       PXA250     SSP
 *       PXA255     SSP, NSSP
 *       PXA26x     SSP, NSSP, ASSP
 *       PXA27x     SSP1, SSP2, SSP3
 */

#ifndef SSP_H
#define SSP_H

#include "monahans.h"
#include "util.h"

#define    CKEN_SSP1    26    /* < SSP1 clock enable */
#define    CKEN_SSP2    27    /* < SSP2 clock enable */
#define    CKEN_SSP3    28    /* < SSP3 clock enable */

#define SSSR_BCE        (1 << 23)    /* Bit Count Error */
#define SSSR_CSS        (1 << 22)    /* Clock Synchronisation Status */
#define SSSR_TUR        (1 << 21)    /* Transmit FIFO Under Run */
#define SSSR_EOC        (1 << 20)    /* End Of Chain */
#define SSSR_TINT        (1 << 19)    /* Receiver Time-out Interrupt */
#define SSSR_PINT        (1 << 18)    /* Peripheral Trailing Byte Interrupt */

#define SSTO_P1        __REG(0x41000028)  /* SSP Port 1 Time Out Register */
#define SSPSP_P1    __REG(0x4100002C)  /* SSP Port 1 Programmable Serial Protocol */
#define SSTSA_P1    __REG(0x41000030)  /* SSP Port 1 Tx Timeslot Active */
#define SSRSA_P1    __REG(0x41000034)  /* SSP Port 1 Rx Timeslot Active */
#define SSTSS_P1    __REG(0x41000038)  /* SSP Port 1 Timeslot Status */
#define SSACD_P1    __REG(0x4100003C)  /* SSP Port 1 Audio Clock Divider */
#define SSCR0_P2    __REG(0x41700000)  /* SSP Port 2 Control Register 0 */
#define SSCR1_P2    __REG(0x41700004)  /* SSP Port 2 Control Register 1 */
#define SSSR_P2        __REG(0x41700008)  /* SSP Port 2 Status Register */
#define SSITR_P2        __REG(0x4170000C)  /* SSP Port 2 Interrupt Test Register */
#define SSDR_P2        __REG(0x41700010)  /* (Write / Read) SSP Port 2 Data Write Register/SSP Data Read Register */
#define SSTO_P2        __REG(0x41700028)  /* SSP Port 2 Time Out Register */
#define SSPSP_P2    __REG(0x4170002C)  /* SSP Port 2 Programmable Serial Protocol */
#define SSTSA_P2    __REG(0x41700030)  /* SSP Port 2 Tx Timeslot Active */
#define SSRSA_P2    __REG(0x41700034)  /* SSP Port 2 Rx Timeslot Active */
#define SSTSS_P2    __REG(0x41700038)  /* SSP Port 2 Timeslot Status */
#define SSACD_P2    __REG(0x4170003C)  /* SSP Port 2 Audio Clock Divider */
#define    SSACDD_P2    __REG(0x41700040)  /* SSP Port 2 Audio Clock Dither Divider Register */

#define SSCR0_P3    __REG(0x41900000)  /* SSP Port 3 Control Register 0 */
#define SSCR1_P3    __REG(0x41900004)  /* SSP Port 3 Control Register 1 */
#define SSSR_P3        __REG(0x41900008)  /* SSP Port 3 Status Register */
#define SSITR_P3        __REG(0x4190000C)  /* SSP Port 3 Interrupt Test Register */
#define SSDR_P3        __REG(0x41900010)  /* (Write / Read) SSP Port 3 Data Write Register/SSP Data Read Register */
#define SSTO_P3        __REG(0x41900028)  /* SSP Port 3 Time Out Register */
#define SSPSP_P3    __REG(0x4190002C)  /* SSP Port 3 Programmable Serial Protocol */
#define SSTSA_P3    __REG(0x41900030)  /* SSP Port 3 Tx Timeslot Active */
#define SSRSA_P3    __REG(0x41900034)  /* SSP Port 3 Rx Timeslot Active */
#define SSTSS_P3    __REG(0x41900038)  /* SSP Port 3 Timeslot Status */
#define SSACD_P3    __REG(0x4190003C)  /* SSP Port 3 Audio Clock Divider */
#define SSACDD_P3    __REG(0x41900040)  /* SSP Port 3 Audio Clock Dither Divider Register */

#define SSCR0_P4        __REG(0x41A00000)  /* SSP Port 4 Control Register 0 */
#define SSCR1_P4        __REG(0x41A00004)  /* SSP Port 4 Control Register 1 */
#define SSSR_P4         __REG(0x41A00008)  /* SSP Port 4 Status Register */
#define SSITR_P4        __REG(0x41A0000C)  /* SSP Port 4 Interrupt Test Register */
#define SSDR_P4         __REG(0x41A00010)  /* (Write / Read) SSP Port 4 Data Write Register/SSP Data Read Register */
#define SSTO_P4         __REG(0x41A00028)  /* SSP Port 4 Time Out Register */
#define SSPSP_P4        __REG(0x41A0002C)  /* SSP Port 4 Programmable Serial Protocol */
#define    SSTSA_P4    __REG(0x41A00030)  /* SSP Port 4 TX Time Slot Active Register */
#define    SSRSA_P4    __REG(0x41A00034)  /* SSP Port 4 RX Time Slot Active Register */
#define    SSTSS_P4    __REG(0x41A00038)  /* SSP Port 4 Time Slot Status Register */
#define    SSACD_P4    __REG(0x41A0003C)  /* SSP Port 4 Audio Clock Divider Register */
#define    SSACDD_P4    __REG(0x41A00040)  /* SSP Port 4 Audio Clock Dither Divider Register */

#define SSCR0_P1    __REG(0x41000000)  /* SSP Port 1 Control Register 0 */
#define SSCR1_P1    __REG(0x41000004)  /* SSP Port 1 Control Register 1 */
#define SSSR_P1        __REG(0x41000008)  /* SSP Port 1 Status Register */
#define SSITR_P1           __REG(0x4100000C)  /* SSP Port 1 Interrupt Test Register */
#define SSDR_P1        __REG(0x41000010)  /* (Write / Read) SSP Port 1 Data Write Register/SSP Data Read Register */

#define SSCR0_P(x) (*(((x) == 1) ? &SSCR0_P1 : ((x) == 2) ? &SSCR0_P2 : ((x) == 3) ? &SSCR0_P3 : ((x) == 4) ? &SSCR0_P4 : NULL))
#define SSCR1_P(x) (*(((x) == 1) ? &SSCR1_P1 : ((x) == 2) ? &SSCR1_P2 : ((x) == 3) ? &SSCR1_P3 : ((x) == 4) ? &SSCR1_P4 : NULL))
#define SSSR_P(x) (*(((x) == 1) ? &SSSR_P1 : ((x) == 2) ? &SSSR_P2 : ((x) == 3) ? &SSSR_P3 : ((x) == 4) ? &SSSR_P4 : NULL))
#define SSITR_P(x) (*(((x) == 1) ? &SSITR_P1 : ((x) == 2) ? &SSITR_P2 : ((x) == 3) ? &SSITR_P3 : ((x) == 4) ? &SSITR_P4 : NULL))
#define SSDR_P(x) (*(((x) == 1) ? &SSDR_P1 : ((x) == 2) ? &SSDR_P2 : ((x) == 3) ? &SSDR_P3 : ((x) == 4) ? &SSDR_P4 : NULL))
#define SSTO_P(x) (*(((x) == 1) ? &SSTO_P1 : ((x) == 2) ? &SSTO_P2 : ((x) == 3) ? &SSTO_P3 : ((x) == 4) ? &SSTO_P4 : NULL))
#define SSPSP_P(x) (*(((x) == 1) ? &SSPSP_P1 : ((x) == 2) ? &SSPSP_P2 : ((x) == 3) ? &SSPSP_P3 : ((x) == 4) ? &SSPSP_P4 : NULL))
#define SSTSA_P(x) (*(((x) == 1) ? &SSTSA_P1 : ((x) == 2) ? &SSTSA_P2 : ((x) == 3) ? &SSTSA_P3 : ((x) == 4) ? &SSTSA_P4 : NULL))
#define SSRSA_P(x) (*(((x) == 1) ? &SSRSA_P1 : ((x) == 2) ? &SSRSA_P2 : ((x) == 3) ? &SSRSA_P3 : ((x) == 4) ? &SSRSA_P4 : NULL))
#define SSTSS_P(x) (*(((x) == 1) ? &SSTSS_P1 : ((x) == 2) ? &SSTSS_P2 : ((x) == 3) ? &SSTSS_P3 : ((x) == 4) ? &SSTSS_P4 : NULL))
#define SSACD_P(x) (*(((x) == 1) ? &SSACD_P1 : ((x) == 2) ? &SSACD_P2 : ((x) == 3) ? &SSACD_P3 : ((x) == 4) ? &SSACD_P4 : NULL))
#define SSACDD_P(x) (*(((x) == 2) ? &SSACDD_P2 : ((x) == 3) ? &SSACDD_P3 : ((x) == 4) ? &SSACDD_P4 : NULL))


#define SSSR_TNF    (1 << 2)    /* Transmit FIFO Not Full */
#define SSSR_RNE    (1 << 3)    /* Receive FIFO Not Empty */
#define SSSR_BSY    (1 << 4)    /* SSP Busy */
#define SSSR_TFS    (1 << 5)    /* Transmit FIFO Service Request */
#define SSSR_RFS    (1 << 6)    /* Receive FIFO Service Request */
#define SSSR_ROR    (1 << 7)    /* Receive FIFO Overrun */

#define SSCR0_TIM        (1 << 23)    /* Transmit FIFO Under Run Interrupt Mask */
#define SSCR0_RIM        (1 << 22)    /* Receive FIFO Over Run interrupt Mask */
#define SSCR0_NCS        (1 << 21)    /* Network Clock Select */
#define SSCR0_EDSS        (1 << 20)    /* Extended Data Size Select */

#define SSCR0_SSE    (1 << 7)    /* Synchronous Serial Port Enable */

/*
 * Core Clock
 */
#if 1
#define ACCR        __REG(0x41340000)    /* Application Subsystem Clock Configuration Register */
#define ACSR        __REG(0x41340004)    /* Application Subsystem Clock Status Register */
#define AICSR        __REG(0x41340008)    /* Application Subsystem Interrupt Control/Status Register */
#define CKENA        __REG(0x4134000C)    /* A Clock Enable Register */
#define CKENB        __REG(0x41340010)    /* B Clock Enable Register */
#define AC97_DIV    __REG(0x41340014)    /* AC97 clock divisor value register */
#define OSCC        __REG(0x41350000)    /* Oscillator Configuration Register */

#define OSCC_PEN    (1 << 11)

/* Clock Enable Register (CLKEN) Enum */
#define    CKEN_LCD    1    /* < LCD Clock Enable */
#define    CKEN_USBH    2    /* < USB host clock enable */
#define    CKEN_CAMERA    3    /* < Camera interface clock enable */
#define    CKEN_NAND    4    /* < NAND Flash Controller Clock Enable */

#define CKEN_MMC3    5    /* < MMC3 Clock Enable */

#define    CKEN_USB2    6    /* < USB 2.0 client clock enable. */

#define CKEN_GRAPHICS    42

#define    CKEN_DMC    8    /* < Dynamic Memory Controller clock enable */
#define    CKEN_SMC    9    /* < Static Memory Controller clock enable */
#define    CKEN_ISC    10    /* < Internal SRAM Controller clock enable */
#define    CKEN_BOOT    11    /* < Boot rom clock enable */
#define    CKEN_MMC1    12    /* < MMC1 Clock enable */
#define    CKEN_MMC2    13    /* < MMC2 clock enable */
#define    CKEN_KEYPAD    14    /* < Keypand Controller Clock Enable */
#define    CKEN_CIR    15    /* < Consumer IR Clock Enable */
#define    CKEN_USIM0    17    /* < USIM[0] Clock Enable */
#define    CKEN_USIM1    18    /* < USIM[1] Clock Enable */
#define    CKEN_TPM    19    /* < TPM clock enable */
#define    CKEN_UDC    20    /* < UDC clock enable */
#define    CKEN_BTUART    21    /* < BTUART clock enable */
#define    CKEN_FFUART    22    /* < FFUART clock enable */
#define    CKEN_STUART    23    /* < STUART clock enable */
#define    CKEN_AC97    24    /* < AC97 clock enable */
#define    CKEN_TOUCH    25    /* < Touch screen Interface Clock Enable */
#define    CKEN_SSP1    26    /* < SSP1 clock enable */
#define    CKEN_SSP2    27    /* < SSP2 clock enable */
#define    CKEN_SSP3    28    /* < SSP3 clock enable */
#define    CKEN_SSP4    29    /* < SSP4 clock enable */
#define    CKEN_MSL0    30    /* < MSL0 clock enable */

#define    CKEN_PWM0    32    /* < PWM[0] clock enable */
#define    CKEN_PWM1    33    /* < PWM[1] clock enable */
#define    CKEN_I2C    36    /* < I2C clock enable */
#define    CKEN_INTC    38    /* < Interrupt controller clock enable */
#define    CKEN_GPIO    39    /* < GPIO clock enable */
#define    CKEN_1WIRE    40    /* < 1-wire clock enable */
#define CKEN_HSIO2    41    /* < HSIO2 clock enable */

#define CKEN_MVED    43    /* < MVED clock enable */
#define    CKEN_MINI_IM    48    /* < Mini-IM */
#define    CKEN_MINI_LCD    49    /* < Mini LCD */

#endif
void pxa_set_cken(int clock, int enable);
/*
 * SSP initialisation flags
 */
#define SSP_NO_IRQ    0x1        /* don't register an irq handler in SSP driver */
//#define u32 unsigned int
//typedef unsigned int u32
struct ssp_state {
    u32    cr0;
    u32 cr1;
    u32 to;
    u32 psp;
};

struct ssp_dev {
    u32 port;
    u32 mode;
    u32 flags;
    u32 psp_flags;
    u32 speed;
    int irq;
};
void pxa_set_cken(int clock, int enable);

int ssp_write_word(struct ssp_dev *dev, u32 data);
int ssp_read_word(struct ssp_dev *dev, u32 *data);
int ssp_flush(struct ssp_dev *dev);
void ssp_enable(struct ssp_dev *dev);
void ssp_disable(struct ssp_dev *dev);
void ssp_save_state(struct ssp_dev *dev, struct ssp_state *ssp);
void ssp_restore_state(struct ssp_dev *dev, struct ssp_state *ssp);
int ssp_init(struct ssp_dev *dev, u32 port, u32 init_flags);
int ssp_config(struct ssp_dev *dev, u32 mode, u32 flags, u32 psp_flags, u32 speed);
void ssp_exit(struct ssp_dev *dev);

#endif
